package dnl.math.graph2d;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.math.util.FastMath;

public class EquiArcCalc {

    private double r;
    private int n;
    private int numOfLevels;
    private List<MathCoordinatesPoint> points = new ArrayList<MathCoordinatesPoint>();

    /**
     * The number of arcs for all circles.
     *
     * @return
     */
    public int getN() {
        return n;
    }

    public void setN(int n) {
        this.n = n;
    }

    /**
     * Gets the number of circle levels when drawing a 'flower of life' structure.
     *
     * @return
     */
    public int getNumOfLevels() {
        return numOfLevels;
    }

    public void setNumOfLevels(int numOfLevels) {
        this.numOfLevels = numOfLevels;
    }

    public double getR() {
        return r;
    }

    /**
     *
     * @param r the radius as a real number.
     */
    public void setR(double r) {
        this.r = r;
    }

    public EquiArcCalc(final double r, final int n, final int numOfLevels) {
        this.r = r;
        this.n = n;
        this.numOfLevels = numOfLevels;
    }

    public MathCoordinatesPoint[] getEquiArcPoints(final MathCoordinatesPoint p) {
        double x0 = p.x, y0 = p.y;
        double angleIntervalRad = FastMath.PI * 2 / n;

        MathCoordinatesPoint[] ecPoints = new MathCoordinatesPoint[n];
        for (int i = 0; i < ecPoints.length; i++) {
            ecPoints[i] = new MathCoordinatesPoint();
        }

        for (int i = 0; i < n; i++) {
            double angle = angleIntervalRad * i;
            ecPoints[i].x = x0 + r * FastMath.cos(angle);
            ecPoints[i].y = y0 + r * FastMath.sin(angle);
        }
        return ecPoints;
    }

    public List<MathCoordinatesPoint> getEquiArcLevels(final MathCoordinatesPoint root) {
        points.clear();
        points.add(root);
        getEquiArcLevelsImpl(root, 1);
        return points;
    }

    private void getEquiArcLevelsImpl(final MathCoordinatesPoint root, final int level) {
        if (level == numOfLevels) {
            return;
        }
        MathCoordinatesPoint[] equiArcPoints = getEquiArcPoints(root);
        for (MathCoordinatesPoint p : equiArcPoints) {
            points.add(p);
            getEquiArcLevelsImpl(p, level + 1);
        }
    }
}
